package main

import (
	"fmt"
	"log"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var db *gorm.DB
var err error
var students []*Student
var rows *gorm.DB

func init() {
	// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
	// dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
	dsn := "jin:jin@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: logger.Default.LogMode(logger.Info),
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(db)
}

// 不符合约定的定义，很多都需要配置，直接用不行
type Emp struct { // 默认表名emps
	emp_no     int    `gorm:"primaryKey"` // 不是ID为主键，需要配置
	first_name string // 首字母未大写，也需要配置
	last_name  string
	gender     byte
	birth_date string
}

func (Emp) TableName() string {
	return "employees"
}

type Student struct {
	ID       int        // 缺省主键bigint AUTO_INCREMENT
	Name     string     `gorm:"not null;type:varchar(48);comment:姓名"`
	Age      byte       // `gorm:"size:32"` // byte=>tinyint unsigned
	Birthday *time.Time // datetime
	Gender   byte       // `gorm:"type:tinyint"`
}

func (s *Student) String() string {
	return fmt.Sprintf("%d", s.ID)
}

func main() {
	// var e Emp
	// row := db.Take(&e) // 等价于Limit 1，取1条
	// fmt.Println(row)
	// fmt.Println(row.Error)
	// fmt.Println(e)
	// fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

	// 迁移表
	// db.Migrator().DropTable(&Student{})
	// db.Migrator().CreateTable(&Student{})

	// 新增1条记录
	// n := time.Now()
	// s := Student{Name: "tom", Age: 20, Birthday: &n}
	// fmt.Println(s)
	// result := db.Create(&s)
	// fmt.Println(s)
	// fmt.Println(result.Error)
	// fmt.Println(result.RowsAffected)

	// 新增多条记录
	// n := time.Now()
	// s := Student{Name: "tomeaa", Age: 20, Birthday: &n}
	// fmt.Println(s)
	// result := db.Create([]*Student{&s, &s, &s})
	// fmt.Println(s)
	// fmt.Println(result.Error)
	// fmt.Println(result.RowsAffected)

	// // 查询 1条
	// var s Student
	// fmt.Println(s)
	// row := db.Take(&s)
	// fmt.Println(s)
	// fmt.Println(row)
	// fmt.Println(row.Error)

	// // 查询整个表格
	// var students []*Student
	// rows := db.Find(&students)
	// fmt.Println(students)
	// fmt.Println(rows)
	// fmt.Printf("rows.Error: %v\n", rows.Error)
	// for _, s := range students {
	// 	fmt.Println(s.ID, s.Name, s.Age, s.Birthday, s.Gender)
	// }

	// distinct 去重
	// var students []*Student
	// rows := db.Distinct("name").Find(&students)
	// fmt.Println(rows)
	// fmt.Printf("rows.Error: %v\n", rows.Error)
	// fmt.Println(students)
	// for _, s := range students {
	// 	fmt.Println(s.Name, s.ID)
	// }

	// // 投影
	// var students []*Student
	// rows := db.Select("id", "name", "age").Find(&students)
	// fmt.Printf("rows.Error: %v\n", rows.Error)
	// fmt.Printf("rows: %v\n", rows)
	// fmt.Println(students)
	// for _, s := range students {
	// 	fmt.Printf("id: %d, name: %s, age: %d\n", s.ID, s.Name, s.Age)
	// }

	// limit
	// rows := db.Limit(2).Offset(2).Find(&students)
	// fmt.Printf("rows: %v\n", rows)

	// where
	rows = db.Where("name = ?", "tom").Find(&students)
	fmt.Printf("rows.Error: %v\n", rows.Error)
	rows = db.Where("name <> ?", "tom").Find(&students)
	fmt.Printf("rows.Error: %v\n", rows.Error)
	rows = db.Where("name in ?", []string{"jerry", "tom"}).Find(&students)
	fmt.Printf("rows.Error: %v\n", rows.Error)
	rows = db.Where("name like ?", "t%").Find(&students)
	fmt.Printf("rows.Error: %v\n", rows.Error)
	rows = db.Where("name like binary ?", "T%").Find(&students)
	fmt.Printf("rows.Error: %v\n", rows.Error)
}
